package pl.com.like.sequoia.dao;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class GenericDao<T, PK extends Serializable> implements IGenericDao<T, PK> {

	private final Class<T> type;
	private SessionFactory session;

	public GenericDao(final Class<T> type) {
		this.type = type;
	}

	/** {@inheritDoc} */
	public void evict(T o) {
		getSession().evict(o);
	}

	/** {@inheritDoc} */
	public boolean exists(PK id) {
		return get(id) != null;
	}

	public void flush() {
		getSession().flush();
	}

	/** {@inheritDoc} */
	@SuppressWarnings("unchecked")
	public T get(PK id) {
		return (T) getSession().get(type, id);
	}

	/** {@inheritDoc} */
	@SuppressWarnings("unchecked")
	public List<T> getAll() {
		return getSession().createCriteria(type).list();
	}

	/** {@inheritDoc} */
	public List<T> getAllDistinct() {
		Collection<T> result = new LinkedHashSet<T>(getAll());
		return new ArrayList<T>(result);
	}

	/** {@inheritDoc} */
	public Criteria getCriteria() {
		return getSession().createCriteria(type);
	}

	protected Session getSession() {
		return session.getCurrentSession();
	}

	/** {@inheritDoc} */
	@SuppressWarnings("unchecked")
	public T load(PK id) {
		return (T) getSession().get(type, id);
	}

	/** {@inheritDoc} */
	@SuppressWarnings( { "unchecked" })
	public T merge(T o) {
		return (T) getSession().merge(o);
	}

	public void refresh(T o) {
		getSession().refresh(o);
	}

	/** {@inheritDoc} */
	public void remove(PK id) {
		this.remove(get(id));
	}

	public void remove(T id) {
		getSession().delete(id);
	}

	public void removeAll(Collection<T> list) {
		if (list != null) {
			for (T item : list) {
				remove(item);
			}
		}
	}

	/** {@inheritDoc} */
	public void save(T o) {
		getSession().save(o);
	}

	/** {@inheritDoc} */
	public void saveOrUpdate(T o) {
		getSession().saveOrUpdate(o);
	}

	/** {@inheritDoc} */
	public void setSession(SessionFactory session) {
		this.session = session;
	}
}
